package com.yunxin.core.application.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.core.util.ObjectUtil;
import com.yunxin.common.exception.BusinessException;
import com.yunxin.common.result.Result;
import com.yunxin.common.result.ResultCode;
import com.yunxin.core.application.admin.team.*;
import com.yunxin.core.application.command.order.OperateAllocationOrderAccountCommand;
import com.yunxin.core.application.command.order.OperateAllocationOrderRest;
import com.yunxin.core.application.command.order.OperateAllocationOrderStatusCommand;
import com.yunxin.core.application.dto.user.SysUser;
import com.yunxin.core.application.service.OrderApplicationAdminService;
import com.yunxin.core.domain.model.order.OrderAllocationBelongToAccount;
import com.yunxin.core.domain.model.order.OrderAllocationBelongToAccountRepository;
import com.yunxin.core.domain.model.order.OrderUserApplyAllocation;
import com.yunxin.core.domain.model.order.OrderUserApplyAllocationRepository;
import com.yunxin.core.domain.service.order.OrderUserApplyAllocationService;
import com.yunxin.core.infra.persistence.mapper.order.OrderTeamTaskDetailMapper;
import com.yunxin.core.infra.persistence.mapper.order.PageQueryCountMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zero°
 * @since 2023-07-12
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderApplicationAdminServiceImpl implements OrderApplicationAdminService {

    private final OrderUserApplyAllocationRepository orderUserApplyAllocationRepository;

    private final OrderUserApplyAllocationService orderUserApplyAllocationService;

    private final OrderAllocationBelongToAccountRepository orderAllocationBelongToAccountRepository;

    private final OrderTeamTaskDetailMapper teamTaskDetailMapper;


    @Override
    public boolean operateAllocationOrderAccount(OperateAllocationOrderAccountCommand request) {
        final Long account = request.getAccountId();
        final String operator = request.getOperator();
        //获取当天时间
        DateTime start = DateUtil.beginOfDay(new Date());
        DateTime end = DateUtil.endOfDay(new Date());
        DateTime now = DateUtil.date();
        //根据商户id和用户id关联关系查询用户id

        SysUser userDto = teamTaskDetailMapper.findUserIdByAccountId(account);
        //根据商户id查询团队信息
        List<Team> teams = teamTaskDetailMapper.findTeamByAccount(request.getAccountId());
        Team team = teams.get(0);
        if (Objects.isNull(team)) return false;
        //查询当天是否已经存在统计表
        List<TeamTaskDistribute> teamTaskDistribute = teamTaskDetailMapper.selectTeamCountByTime(start, end, Arrays.asList(userDto.getId()));
        if (teamTaskDistribute.isEmpty()) {
            //为空新建统计
            teamTaskDetailMapper.insertIntoForCount(userDto.getId(), userDto.getNickname(), (long) team.getId(), team.getTeamName(), 1, now);
        } else {
            //当天已有分配记录，更新二次分配计数
            teamTaskDetailMapper.updateForCountTwo(userDto.getId(),(long) team.getId(), team.getTeamName(), 1, teamTaskDistribute.get(0).getCreatTime());
        }
        AtomicInteger count = new AtomicInteger();
        request.getOrderIds().forEach(x -> {
            OrderUserApplyAllocation allocation = orderUserApplyAllocationRepository.getOrderUserApplyAllocationById(x);
            if (Objects.isNull(allocation)) {
                log.error("操作分配订单失败,订单不存在，id={},accountId={}", x, account);
                return;
            }
            int result = orderUserApplyAllocationService.operateAllocationOrderAccount(allocation, account, operator);
            count.set(count.get() + result);
        });
        return count.get() > 0;
    }

    @Override
    public boolean operateAllocationOrderStatus(OperateAllocationOrderStatusCommand request) {
        OrderUserApplyAllocation allocation = orderUserApplyAllocationRepository.getOrderUserApplyAllocationById(request.getId());
        if (Objects.isNull(allocation)) {
            throw new BusinessException(ResultCode.DATA_NO_EXIST_ERROR);
        }
        allocation.setVersion(allocation.getVersion() + 1);
        allocation.setEditor(request.getOperator());
        allocation.setEditTime(new Date());
        allocation.setOrderStatus(request.getOrderStatus());
        allocation.setRemark(request.getRemark());
        int count = orderUserApplyAllocationRepository.updateOrderUserApplyAllocation(allocation);
        //同时修改任务详情表中订单状态
        Integer status =  teamTaskDetailMapper.getTaskDetailOrder(allocation.getId());
        if (Objects.isNull(status)) return true;
        teamTaskDetailMapper.updateTaskDetailOrderStatus(allocation.getOrderStatus(), allocation.getId());
        return count > 0;
    }


    /**
     * 查询订单已分配团队
     *
     * @param
     * @return
     */
    @Override
    public DistributeResultDto allocatedTeamList(OperateAllocationOrderAccountCommand request) {
        DistributeResultDto resultDto = new DistributeResultDto();
        Set<Team> allocatedTeamName = new HashSet<>();
        request.getOrderIds().forEach(x -> {
            OrderUserApplyAllocation allocation = orderUserApplyAllocationRepository.getOrderUserApplyAllocationById(x);
            if (Objects.isNull(allocation)) {
                log.error("操作分配订单失败,订单不存在，id={}", x);
                return;
            }
            //根据订单查询团队
            OrderAllocationBelongToAccount orderAllocationBelongToAccount = orderAllocationBelongToAccountRepository.getOrderAllocationBelongToAccountByAllocationOrderId(allocation.getId());
            if (Objects.nonNull(orderAllocationBelongToAccount)) {
                //查询出已分配的团队信息
                List<Team> team = orderAllocationBelongToAccountRepository.selecteamName(orderAllocationBelongToAccount.getAllocationOrderId());
                if (CollUtil.isNotEmpty(team)) allocatedTeamName.addAll(team);
            }
        });
        //保存已分配和未分配团队
        if (allocatedTeamName.isEmpty()) {
            //未分配团队返回所有团队
            resultDto.setUndistributedTeamName(orderAllocationBelongToAccountRepository.selectAllTeamName());
            return resultDto;
        }
        allocatedTeamName.removeAll(Collections.singleton(null));
        List<Integer> teamIds = allocatedTeamName.stream().map(Team::getId).toList();
        resultDto.setAllocatedTeamName(allocatedTeamName);
        resultDto.setUndistributedTeamName(orderAllocationBelongToAccountRepository.selecteamNameNo(teamIds));
        return resultDto;
    }


    /**
     * 重新分配
     *
     * @param command
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<DistributeResultDto> operateAllocationOrderRest(OperateAllocationOrderRest command) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //查询当前商户id和任务信息
        Long merchantId = orderUserApplyAllocationService.merchantIdByUserId(command.getUserId());
        if (Objects.isNull(merchantId)) {
            throw new RuntimeException("未查询到当前商户信息！");
        }
        //保存任务
        DistributeDo distributeDo = new DistributeDo();
        distributeDo.setTeamIds(command.getTeamId().toString());
        distributeDo.setMerchantId(merchantId);
        distributeDo.setTeamCont(command.getTeamId().size() - 1);
        distributeDo.setTeamHour(command.getTeamDistributeTime());
        distributeDo.setPersonSecond(command.getPersonDistributeTeam());
        //设置团队和人员下次分配时间
        DateTime startTime = DateUtil.date();
        DateTime personTime = startTime.offset(DateField.SECOND, command.getPersonDistributeTeam());
        DateTime teamTime = startTime.offset(DateField.HOUR, command.getTeamDistributeTime());
        distributeDo.setPersonTime(personTime);
        distributeDo.setTeamTime(teamTime);
        distributeDo.setCreatTime(new DateTime());
        distributeDo.setEditTime(new DateTime());
        //校验订单是否被分配
        List<Integer> teamTaskDetailId = orderUserApplyAllocationService.selectalreadyDistribute(command.getOrderIds());
        if (!teamTaskDetailId.isEmpty()) {
            throw new RuntimeException("已有订单被分配！");
        }
        //保存任务
        orderUserApplyAllocationService.saveTeamTask(distributeDo);
        //根据订单查询订单信息
        List<OrderUserApplyAllocation> orderUserApplyAllocation = orderUserApplyAllocationService.selectOrderDetail(command.getOrderIds());
        //给第一个团队分配订单
        return distribute(orderUserApplyAllocation, command.getTeamId().get(0), distributeDo.getId(), command.getPersonDistributeTeam(), command.getTeamDistributeTime());
    }


    /**
     * 将订单分配到团队
     *
     * @param orderUserApplyAllocation
     */
    private Result<DistributeResultDto> distribute(List<OrderUserApplyAllocation> orderUserApplyAllocation, Long teamId, int taskId, Integer personDistributeTeam, Integer teamDistributeTime) {
        //根据id查询团队
        Team team = teamTaskDetailMapper.findTeam(teamId);
        List<Long> orderIds = orderUserApplyAllocation.stream().map(OrderUserApplyAllocation::getId).toList();
        //将订单分配到团队
        teamTaskDetailMapper.saveOrderToTeam(orderIds, teamId, taskId);
        //分配订单到人员
        List<Long> userIds = teamTaskDetailMapper.selectTeamOfPerson(teamId);
        List<Long> orderId = teamTaskDetailMapper.selectOrderUserAllocationByTaskId(taskId);
        if (userIds.isEmpty() || orderId.isEmpty()) {
            throw new RuntimeException("未查询到团队人员或订单！");
        }
        DateTime start = DateUtil.beginOfDay(new Date());
        DateTime end = DateUtil.endOfDay(new Date());
        DateTime now = DateUtil.date();
        //key : userId      value : count
        Map<Long, Integer> userCountMap = new HashMap<>();
        List<List<Long>> partition = ListUtil.partition(orderId, userIds.size());
        for (List<Long> ids : partition) {
            for (int i = 0; i < ids.size(); i++) {
                //计数统计，将userId和count加入到map
                Long userId = userIds.get(i);
                Integer count = ObjectUtil.defaultIfNull(userCountMap.get(userId), 0);
                count = count + 1;
                userCountMap.put(userId, count);
                //更新订单详情表
                try {
                    teamTaskDetailMapper.distributeOrderUserApply(ids.get(i), userId, DateUtil.date());
                } catch (Exception e) {
                    return Result.failed("改账号未查询到绑定的商户信息！");
                }
                //更新任务详情表
                teamTaskDetailMapper.updateTeamTaskDetail(ids.get(i), userId, DateUtil.date());
            }
        }
        //查询当天是否已经存在统计表
        List<TeamTaskDistribute> teamTaskDistribute = teamTaskDetailMapper.selectTeamCountByTime(start, end, userIds);
        if (teamTaskDistribute.isEmpty()) {
            //为空新建统计
            for (Long userId : userCountMap.keySet()) {
                String userName = teamTaskDetailMapper.getUserNameByUserId(userId);
                teamTaskDetailMapper.insertIntoForCount(userId, userName, teamId, team.getTeamName(), userCountMap.get(userId), now);
            }
        } else {
            for (Long userId : userCountMap.keySet()) {
                //当天已有分配记录，更新二次分配计数
                teamTaskDetailMapper.updateForCountTwo(userId, teamId, team.getTeamName(), userCountMap.get(userId), teamTaskDistribute.get(0).getCreatTime());
            }
        }
        return Result.success();
    }
}
